home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / grafica / amhelios / bitmap24.cpp < prev    next >
C/C++ Source or Header  |  1999-01-01  |  6KB  |  367 lines

  1. /* -------------------------------------------------------------------------- *\
  2.    BITMAP24.CPP
  3.    Copyright © 1997 by Jarno van der Linden
  4.    jarno@kcbbs.gen.nz
  5.  
  6.    24 bit bitmap handling, including IFF24 saving
  7.  
  8.    This program is Freeware, and all usual Freeware rules apply.
  9.  
  10.    21 Feb 1997: Project started
  11. \* -------------------------------------------------------------------------- */
  12.  
  13. /* -------------------------------- Includes -------------------------------- */
  14. #include <dos/dos.h>
  15.  
  16. #include <proto/dos.h>
  17.  
  18. #include <string.h>
  19.  
  20. #include "bitmap24.h"
  21.  
  22. /* ------------------------------ Definitions ------------------------------- */
  23.  
  24. /* --------------------------------- Macros --------------------------------- */
  25.  
  26. /* -------------------------------- Typedefs -------------------------------- */
  27. typedef UBYTE Masking;
  28. #define mskNone    0
  29. typedef UBYTE Compression;
  30. #define cmpNone        0
  31. #define cmpByteRun    1
  32.  
  33. typedef struct {
  34.     UWORD w,h;
  35.     WORD x,y;
  36.     UBYTE nPlanes;
  37.     Masking masking;
  38.     Compression compression;
  39.     UBYTE reserved1;
  40.     UWORD transparentColor;
  41.     UBYTE xAspect,yAspect;
  42.     WORD pageWidth,pageHeight;
  43. } BitMapHeader;
  44.  
  45.  
  46. /* ------------------------------ Proto Types ------------------------------- */
  47.  
  48. /* -------------------------------- Structs --------------------------------- */
  49.  
  50. /* -------------------------------- Globals --------------------------------- */
  51.  
  52. /* ---------------------------------- Code ---------------------------------- */
  53. BitMap24::BitMap24(UWORD width_arg, UWORD height_arg)
  54. {
  55.     error = BITMAP24_ERROR_NONE;
  56.  
  57.     width = width_arg;
  58.     height = height_arg;
  59.  
  60.     width += (16-(width & 15)) & 15;
  61.     bytewidth = width >> 3;
  62.  
  63.     bitmap = new Colour[width*height];
  64.     if(bitmap)
  65.         memset(bitmap,0,width*height*sizeof(Colour));
  66.     else
  67.         error = BITMAP24_ERROR_NOBITMAP;
  68. }
  69.  
  70.  
  71. BitMap24::~BitMap24()
  72. {
  73.     if(bitmap)
  74.         delete bitmap;
  75. }
  76.  
  77.  
  78. int BitMap24::GetError()
  79. {
  80.     return error;
  81. }
  82.  
  83.  
  84. BOOL BitMap24::HasError()
  85. {
  86.     return error != BITMAP24_ERROR_NONE;
  87. }
  88.  
  89.  
  90. char *BitMap24::GetErrorStr()
  91. {
  92.     switch(error)
  93.     {
  94.         case BITMAP24_ERROR_NONE:
  95.             return "No error";
  96.         case BITMAP24_ERROR_NOBITMAP:
  97.             return "BitMap couldn't be allocated";
  98.         case BITMAP24_ERROR_FILEOPEN:
  99.             return "Error opening output file";
  100.         case BITMAP24_ERROR_OUTOFBOUNDS:
  101.             return "Out of bounds coordinate used";
  102.     }
  103.  
  104.     return "Unknown error";
  105. }
  106.  
  107.  
  108.  
  109. UWORD BitMap24::GetWidth()
  110. {
  111.     return width;
  112. }
  113.  
  114.  
  115. UWORD BitMap24::GetHeight()
  116. {
  117.     return height;
  118. }
  119.  
  120.  
  121. BOOL BitMap24::BoundsCheck(int x,int y)
  122. {
  123.     if((x < 0) || (x >= width) || (y < 0) || (y >= height))
  124.     {
  125.         error = BITMAP24_ERROR_OUTOFBOUNDS;
  126.         return FALSE;
  127.     }
  128.  
  129.     return TRUE;
  130. }
  131.  
  132.  
  133. void BitMap24::GetColour(Colour *c,int x,int y)
  134. {
  135.     if(BoundsCheck(x,y))
  136.         *c = bitmap[y*width+x];
  137. }
  138.  
  139.  
  140. UBYTE BitMap24::GetRed(int x,int y)
  141. {
  142.     if(BoundsCheck(x,y))
  143.         return bitmap[y*width+x].r;
  144.  
  145.     return 0;
  146. }
  147.  
  148.  
  149. UBYTE BitMap24::GetGreen(int x,int y)
  150. {
  151.     if(BoundsCheck(x,y))
  152.         return bitmap[y*width+x].g;
  153.  
  154.     return 0;
  155. }
  156.  
  157.  
  158. UBYTE BitMap24::GetBlue(int x,int y)
  159. {
  160.     if(BoundsCheck(x,y))
  161.         return bitmap[y*width+x].b;
  162.  
  163.     return 0;
  164. }
  165.  
  166.  
  167. void BitMap24::SetColour(UBYTE r,UBYTE g,UBYTE b,int x,int y)
  168. {
  169.     Colour *bp;
  170.  
  171.     if(BoundsCheck(x,y))
  172.     {
  173.         bp = &(bitmap[y*width+x]);
  174.         bp->r = r;
  175.         bp->g = g;
  176.         bp->b = b;
  177.     }
  178. }
  179.  
  180.  
  181. void BitMap24::WriteV(BPTR fh,ULONG v)
  182. {
  183.     FWrite(fh,&v,sizeof(v),1);
  184. }
  185.  
  186.  
  187. void BitMap24::WriteB(BPTR fh,UBYTE b)
  188. {
  189.     FWrite(fh,&b,sizeof(b),1);
  190. }
  191.  
  192. void BitMap24::WriteC(BPTR fh, BYTE b)
  193. {
  194.     FWrite(fh,&b,sizeof(b),1);
  195. }
  196.  
  197.  
  198. void BitMap24::WriteP(BPTR fh,void *p,int size)
  199. {
  200.     FWrite(fh,p,size,1);
  201. }
  202.  
  203.  
  204. void BitMap24::WriteS(BPTR fh,char *s)
  205. {
  206.     FWrite(fh,s,strlen(s),1);
  207. }
  208.  
  209.  
  210. UBYTE BitMap24::GatherBits(int row, int c, int b, int x)
  211. {
  212.     UBYTE *bp;
  213.     UBYTE v;
  214.  
  215.     x <<= 3;
  216.     b = 1<<b;
  217.  
  218.     bp = ((UBYTE *)&bitmap[row*width+x]+c);
  219.  
  220.     v = (UBYTE)((*bp & b)!=0);
  221.     bp+=3;
  222.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  223.     bp+=3;
  224.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  225.     bp+=3;
  226.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  227.     bp+=3;
  228.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  229.     bp+=3;
  230.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  231.     bp+=3;
  232.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  233.     bp+=3;
  234.     v = (UBYTE)((v<<1) | ((*bp & b)!=0));
  235.  
  236.     return v;
  237. }
  238.  
  239.  
  240. void BitMap24::WriteRun(BPTR fh, int row, int c, int b, int runstart, int runend)
  241. {
  242.     int x,n;
  243.     UBYTE v;
  244.  
  245.     v = GatherBits(row,c,b,runstart);
  246.  
  247.     for(x=runstart; x<=runend; x+=128)
  248.     {
  249.         n = (runend-x+1);
  250.         if(n > 128)
  251.             n = 128;
  252.  
  253.         WriteC(fh, (BYTE)(-(n-1)));
  254.         WriteB(fh, v);
  255.     }
  256. }
  257.  
  258.  
  259. void BitMap24::WriteDump(BPTR fh, int row, int c, int b, int runstart, int runend)
  260. {
  261.     int xx,x,n;
  262.  
  263.     for(x=runstart; x<=runend; x+=128)
  264.     {
  265.         n = (runend-x+1);
  266.         if(n > 128)
  267.             n = 128;
  268.  
  269.         WriteC(fh, (BYTE)(n-1));
  270.         for(xx=0; xx<n; xx++)
  271.             WriteB(fh, GatherBits(row,c,b,xx+x));
  272.     }
  273. }
  274.  
  275.  
  276.  
  277. void BitMap24::FindRun(int row, int c, int b, int start, int *runstart, int *runlength)
  278. {
  279.     int x;
  280.     UBYTE vs,v;
  281.  
  282.     *runstart = x = start;
  283.     v = GatherBits(row,c,b,x);
  284.  
  285.     while(*runstart < bytewidth)
  286.     {
  287.         vs = v;
  288.         x++;
  289.         while((x < bytewidth) && ((v = GatherBits(row,c,b,x)) == vs))
  290.             x++;
  291.  
  292.         if((*runlength = x-*runstart) > 2)
  293.             return;
  294.  
  295.         *runstart = x;
  296.     }
  297. }
  298.  
  299.  
  300. void BitMap24::WriteBitMap(char *file)
  301. {
  302.     BPTR fh;
  303.     BitMapHeader bmheader;
  304.     int y,c,b;
  305.     int runstart,runlength,runend;
  306.     long lastpos;
  307.  
  308.     bmheader.w = width;
  309.     bmheader.h = height;
  310.     bmheader.x = 0;
  311.     bmheader.y = 0;
  312.     bmheader.nPlanes = 24;
  313.     bmheader.masking = mskNone;
  314.     bmheader.compression = cmpByteRun;
  315.     bmheader.reserved1 = 0;
  316.     bmheader.transparentColor = 0;
  317.     bmheader.xAspect = 1;
  318.     bmheader.yAspect = 1;
  319.     bmheader.pageWidth = (WORD)width;
  320.     bmheader.pageHeight = (WORD)height;
  321.  
  322.     fh = Open(file,MODE_NEWFILE);
  323.     if(!fh)
  324.     {
  325.         error = BITMAP24_ERROR_FILEOPEN;
  326.         return;
  327.     }
  328.  
  329.     WriteS(fh,"FORM");
  330.     WriteV(fh,0);
  331.     WriteS(fh,"ILBMBMHD");
  332.     WriteV(fh,sizeof(bmheader));
  333.     WriteP(fh,&bmheader,sizeof(bmheader));
  334.     WriteS(fh,"BODY");
  335.     WriteV(fh,0);
  336.  
  337.     for(y=0; y<height; y++)
  338.     {
  339.         for(c=0; c<3; c++)
  340.         {
  341.             for(b=0; b<8; b++)
  342.             {
  343.                 runend = 0;
  344.  
  345.                 while(runend < bytewidth)
  346.                 {
  347.                     FindRun(y,c,b, runend, &runstart, &runlength);
  348.                     WriteDump(fh, y,c,b, runend,runstart-1);
  349.                     runend = runstart+runlength;
  350.                     if(runstart < bytewidth)
  351.                         WriteRun(fh, y,c,b, runstart,runend-1);
  352.                 }
  353.             }
  354.         }
  355.     }
  356.  
  357.     lastpos = Seek(fh, 0, OFFSET_CURRENT);
  358.     if(lastpos & 1)
  359.         WriteB(fh,0);
  360.     lastpos = Seek(fh, 4, OFFSET_BEGINNING);
  361.     WriteV(fh,lastpos-Seek(fh, 0, OFFSET_CURRENT)-4);
  362.     Seek(fh, 4+4+8+4+sizeof(bmheader)+4, OFFSET_BEGINNING);
  363.     WriteV(fh, lastpos-Seek(fh, 0, OFFSET_CURRENT)-4);
  364.  
  365.     Close(fh);
  366. }
  367.